﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using ProgNetComponents.Design.Attributes;
using ProgNetComponents.Design.TypeConverters;
using ProgNetComponents.Design.Editors;
using System.Drawing.Design;
using ProgNetComponents.Validation.Design;

namespace ProgNetComponents.Validation.Rules
{
    /// <summary>
    /// Base rule for checking multiple columns
    /// </summary>
    public abstract class MultiColumnsValidationRule : ValidationRule, IDataValidationRule
    {
        /// <summary>
        /// Gets or sets the data source.
        /// </summary>
        /// <value>
        /// The data source.
        /// </value>
        internal System.Data.DataTable DataSource { get; set; }

        #region Members
        /// <summary>
        /// The error string
        /// </summary>
        protected string _ErrorString;
        #endregion

        #region Properties
        /// <summary>
        /// Gets or sets columns that will be validated
        /// </summary>
        /// <value>
        /// The columns.
        /// </value>
        [TypeConverter(typeof(StringArrayTypeConverter))]
        [Editor(typeof(IDataValidationRuleColumnNameTabEditor), typeof(UITypeEditor))]
        public string[] Columns
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets Error to be set if validation fails
        /// </summary>
        /// <value>
        /// The error string.
        /// </value>
        [SerializationVisibilityByMethodAttribute("SerializeErrorString")]
        public string ErrorString
        {
            get
            {
                if (_ErrorString.IsNull())
                    return DefaultErrorString;
                return _ErrorString;
            }
            set { _ErrorString = value; }
        }

        /// <summary>
        /// Gets default error string
        /// </summary>
        /// <value>
        /// The default error string.
        /// </value>
        protected virtual string DefaultErrorString
        {
            get { return null; }
        }

        /// <summary>
        /// Gets formatted error string
        /// </summary>
        /// <value>
        /// The formated error string.
        /// </value>
        public virtual string FormatedErrorString
        {
            get { return ErrorString; }
        }
        #endregion

        /// <summary>
        /// Initializes a new instance of the <see cref="MultiColumnsValidationRule"/> class.
        /// </summary>
        public MultiColumnsValidationRule()
        {

        }
        /// <summary>
        /// Initializes a new instance of the <see cref="MultiColumnsValidationRule"/> class.
        /// </summary>
        /// <param name="columns">The columns.</param>
        /// <param name="error">The error.</param>
        public MultiColumnsValidationRule(string[] columns, string error = null)
        {
            Columns = columns;
            ErrorString = error;
        }

        /// <summary>
        /// Called when [validation failed].
        /// </summary>
        /// <param name="row">The row.</param>
        protected override void OnValidationFailed(System.Data.DataRow row)
        {
            SetColumnsErrors(row, FormatedErrorString);
        }

        /// <summary>
        /// Sets the columns errors.
        /// </summary>
        /// <param name="row">The row.</param>
        /// <param name="error">The error.</param>
        protected void SetColumnsErrors(System.Data.DataRow row, string error)
        {
            foreach (string column in Columns)
            {
                row.SetColumnError(column, error);
            }
        }

        /// <summary>
        /// Serializes the error string.
        /// </summary>
        /// <returns></returns>
        protected virtual DesignerSerializationVisibility SerializeErrorString()
        {
            if (_ErrorString.IsNotNull())
                return DesignerSerializationVisibility.Visible;
            return DesignerSerializationVisibility.Hidden;
        }

        /// <summary>
        /// Gets or sets the data source.
        /// </summary>
        /// <value>
        /// The data source.
        /// </value>
        System.Data.DataTable IDataValidationRule.DataSource
        {
            get;
            set;
        }
    }
}
